package com.kintreda.common.oauth.annotation;

import com.alibaba.fastjson.JSONObject;
import com.kintreda.common.config.enums.UserTypeEnum;
import com.kintreda.common.mybatis.entity.SysAdmin;
import com.kintreda.common.mybatis.entity.SysLog;
import com.kintreda.common.mybatis.entity.SysUser;
import com.kintreda.common.mybatis.service.ISysLogService;
import com.kintreda.common.oauth.jwt.JwtConfig;
import com.kintreda.common.oauth.jwt.JwtUtils;
import com.kintreda.common.oauth.security.service.UserService;
import com.kintreda.tools.utils.HttpContextUtils;
import com.kintreda.tools.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Slf4j
@Component
public class SetLogAspect {

    @Autowired
    private ISysLogService iSysLogService;
    @Autowired
    private UserService userService;

    @Value("${spring.application.name}")
    private String service;

    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation( com.kintreda.common.oauth.annotation.SetLog)")
    public void logPointCut() {
    }

    //切面 配置通知
    @AfterReturning("logPointCut()")
    public void saveSysLog(JoinPoint joinPoint) throws Exception{
        //保存日志
        SysLog sysLog = new SysLog();
        sysLog.setService(service);
        sysLog.setCreateTime(LocalDateTime.now());
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作
        SetLog setLog = method.getAnnotation(SetLog.class);
        if (setLog != null) {
            String value = setLog.value();
            sysLog.setOperation(value);//保存获取的操作
        }
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setMethod(className + "." + methodName);

        //请求的参数
        Object[] args = joinPoint.getArgs();
        //将参数所在的数组转换成json
        try {
            String params = JSONObject.toJSONString(args);
            sysLog.setParams(params);
        }catch (Exception e){
            sysLog.setParams("参数转换错误,可能是无参数请求!");
        }

        //获取用户ip地址
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        sysLog.setIp(IpUtils.getIpAddr(request));

        //操作的用户信息
        String token = request.getHeader(JwtConfig.HEADER);
        if (StringUtils.isNotBlank(token)){
            String userType = JwtUtils.getUserType(request);
            Integer userId = JwtUtils.getUserId(request);
            if (userType.equals(UserTypeEnum.后台管理员.getType())){
                SysAdmin admin = userService.getCurrentUser(userType, userId.toString(), SysAdmin.class);
                sysLog.setUsername(admin.getName());
            }
            if (userType.equals(UserTypeEnum.用户.getType())){
                SysUser user = userService.getCurrentUser(userType, userId.toString(), SysUser.class);
                sysLog.setUsername(user.getNickName());
            }
        }

        //保存SysLog实体类到数据库
        iSysLogService.save(sysLog);

    }

}
